#include <stdlib.h>
#include <string.h>
#include "TokenList.h"

int curIndex = 0;
int lastIndex = 0;
int backTokenFlag = 0;
DynamicListC tokenList;

extern int yylex();
void addToken(const Token *token);

void initializeTokenList()
{
	lastIndex = TOKENS_PER_LIST_BLOCK;
	listInit(&tokenList);
}

void clearTokenList()
{
	ListNode node;
	int i;

	for (listSelectFirst(tokenList); listSelectCurrent(tokenList, NULL); listSelectNext(tokenList, NULL))
	{
		node = listSelectCurrent(tokenList, NULL);
		for (i = 0; i < TOKENS_PER_LIST_BLOCK; i++)
		{
			free(node->type[i].lexeme);
		}
	}

	listFree(&tokenList);
}

void addNewToken(eTokenType tokenType, int line, int column, char* lexeme)
{
	Token token;

	token.type = tokenType;
	token.lineNumber = line;
	token.columnNumber = column;
	token.lexeme = strdup(lexeme);
	addToken(&token);
}

void addToken(const Token *token)
{
	static ListNode node;

	if (lastIndex == TOKENS_PER_LIST_BLOCK)
	{
		ListNode temp = listSelectCurrent(tokenList, NULL);
		// Allocate new block of tokens
		Token *tokenBlock = (Token*)calloc(TOKENS_PER_LIST_BLOCK, sizeof(Token));

		// Add block of tokens to the end of the list
		listInsertAfterEnd(tokenList, &tokenBlock);

		// Get last token block
		node = listSelectLast(tokenList);
		listSelectCurrent(tokenList, temp);
		lastIndex = 0;
	}
	
	// Copy data to token list
	memcpy(&node->type[lastIndex++], token, sizeof(Token));
}

Token *currentToken()
{
	backToken();
	return nextToken();
}

Token *nextToken()
{
	Token *token = NULL;
	ListNode node;

	if (backTokenFlag <= 0)
	{
		yylex();
		backTokenFlag = 0;
	}
	else
	{
		backTokenFlag--;
	}

	if (curIndex == TOKENS_PER_LIST_BLOCK)
	{
		curIndex = 0;
		listSelectNext(tokenList, NULL);
	}

	node = listSelectCurrent(tokenList, NULL);
	if (node)
	{
		token = &node->type[curIndex++];
	}

	return token;
}

void backToken()
{
	if (curIndex == 0)
	{
		curIndex = TOKENS_PER_LIST_BLOCK;
		listSelectPrevious(tokenList, NULL);
	}

	curIndex--;
	backTokenFlag++;
}